package com.fly.core.dyn;

import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

@Component
public class DynSQL
{
    private static final Logger LOGGER = LoggerFactory.getLogger(DynSQL.class);
    
    private Map<String, SQL> mappedStatements = new HashMap<>();
    
    /**
     * 默认构造函数
     * 
     * @throws DocumentException
     */
    public DynSQL()
    {
        super();
        init();
    }
    
    /**
     * 初始化
     * 
     * @see [类、类#方法、类#成员]
     */
    private synchronized void init()
    {
        try
        {
            // 新增sqlxml文件在此添加
            mappedStatements.clear();
            parse("/dyn/001.xml");
        }
        catch (DocumentException e)
        {
            LOGGER.error(e.getMessage(), e);
        }
    }
    
    /**
     * 解析xml文件,DOM4J
     * 
     * @param args
     * @throws DocumentException
     * @throws Exception
     * @see [类、类#方法、类#成员]
     */
    @SuppressWarnings("unchecked")
    private void parse(String path)
        throws DocumentException
    {
        LOGGER.info("-----init: {} -------", path);
        URL url = SAXReader.class.getResource(path);
        Document doc = new SAXReader().read(url);
        XPath xPath = doc.createXPath("/sqlMap/sql");
        Element root = doc.getRootElement();
        String name = root.attributeValue("name");
        Assert.hasText(name, "There is NULL name in this SqlMap XML.");
        LOGGER.info("-----success parse name: {} -------", name);
        List<Element> list = xPath.selectNodes(root);
        for (Element element : list)
        {
            // 验证 id
            String id = element.attributeValue("id");
            Assert.hasText(id, "There is NULL sqlId in this SqlMap XML.");
            // 验证 key
            String key = new StringBuffer(name).append(".").append(id).toString();
            if (mappedStatements.containsKey(key))
            {
                throw new IllegalArgumentException("There is already a sqlId named " + id + " in this SqlMap XML.");
            }
            SQL sql = new SQL();
            sql.setMainSql(element.getText());
            mappedStatements.put(key, sql);
            LOGGER.info("-----success add sqlId: {} -------", id);
        }
    }
    
    /**
     * 根据sqlId查询sql语句
     * 
     * @param sqlId
     * @return
     * @see [类、类#方法、类#成员]
     */
    public String getSqlById(String sqlId)
    {
        if (!mappedStatements.containsKey(sqlId))
        {
            throw new IllegalArgumentException("There is no sqlId named " + sqlId + " in this SqlMap XML.");
        }
        // 处理动态条件
        SQL sql = mappedStatements.get(sqlId);
        return sql.getMainSql();
    }
}

/**
 * 
 * sqlxml文件对应的SQL对象
 * 
 * @author 00fly
 * @version [版本号, 2018年1月5日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
final class SQL
{
    /**
     * sql主句
     */
    private String mainSql;
    
    public String getMainSql()
    {
        return mainSql;
    }
    
    public void setMainSql(String mainSql)
    {
        this.mainSql = mainSql;
    }
}
